package net.orange.framework.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import net.orange.architecture.model.BaseValueObject;
import net.orange.architecture.validator.NotDulicateValidator;
import net.orange.architecture.validator.SetNotNullValidator;
import net.orange.architecture.validator.StringNotNullValidator;
import net.orange.architecture.validator.Validator;

/**
 * The system resource, which is the system internal security control object. it
 * is assign to special groups.it can prevent the user use the special java
 * class or method(which is define a string URL: such as
 * DepartmentProcess@update, it means the update method in DepartmentProcess
 * class, * for all method).it has three types: 1)Public, everyone
 * access.2)Internal, Only the login user can access. 3)Restrict, Only the
 * authorize user can access.
 */
@Entity
@Table(name = "t_resource")
public class Resource extends BaseValueObject {

	private static final long serialVersionUID = -2188498824201332894L;

	/**
	 * The resource define URL,such as DepartmentProcess@update, it means the
	 * update method in DepartmentProcess class, * for all method
	 */
	@Column(name = "resourceurl")
	private String resource;

	/**
	 * The name
	 */
	@Column(name = "name")
	private String name;

	/**
	 * The type
	 */
	@Column(name = "type")
	private String type;

	/**
	 * The description
	 */
	@Column(name = "description")
	private String description;

	/**
	 * The assigned groups
	 */
	@ManyToMany(targetEntity = net.orange.framework.model.Group.class, cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
	@JoinTable(name = "t_resource_group", joinColumns = { @JoinColumn(name = "resource_pk") }, inverseJoinColumns = { @JoinColumn(name = "group_pk") })
	private Set<Group> groups = new HashSet<Group>();

	/**
	 * @return Returns the Type name.
	 */
	public String getTypename() {
		return (type != null) ? ResourceType.parseOf(type).name() : null;
	}

	/**
	 * @return Returns the description.
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * @return Returns the name.
	 */
	public String getName() {
		return name;
	}

	/**
	 * @return Returns the resource.
	 */
	public String getResource() {
		return resource;
	}

	/**
	 * @return Returns the type.
	 */
	public String getType() {
		return type;
	}

	/**
	 * @param description
	 *            The description to set.
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * @param name
	 *            The name to set.
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @param resource
	 *            The resource to set.
	 */
	public void setResource(String resource) {
		this.resource = resource;
	}

	/**
	 * @param type
	 *            The type to set.
	 */
	public void setType(String type) {
		this.type = type;
	}

	/**
	 * @return Returns the groups.
	 */
	public Set<Group> getGroups() {
		return groups;
	}

	/**
	 * @param groups
	 *            The groups to set.
	 */
	public void setGroups(Set<Group> groups) {
		this.groups = groups;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.orange.architecture.model.BaseValueObject#satisfy(java.util.Collection
	 * )
	 */
	public boolean satisfy(Collection<String> msg) throws Exception {
		if (msg == null)
			msg = new ArrayList<String>();

		// name,url,type can't be empty.
		Validator validator = new Validator(msg);

		validator.add(new StringNotNullValidator(getType(), "type"));
		validator.add(new StringNotNullValidator(getName(), "name"));
		validator.add(new StringNotNullValidator(getResource(), "resource"));
		if (getType() != null && getType().equals(ResourceType.Restrict))
			validator.add(new SetNotNullValidator(getGroups(), "group"));

		validator
				.add(new NotDulicateValidator(this, "resource", "resource url"));
		validator.validate();

		return (msg == null || msg.size() <= 0);
	}
}
